import express from 'express';
import http from 'http';
import https from 'https';
import {AddressInfo} from 'net';
import {MiddlewareFactory} from '../middleware/MiddlewareFactory';
import {Logger} from '../utils/Logger';
import {FileUtils} from '../utils/FileUtils';
import {ServerConfig} from '../types';
import path from 'path';
import {exec} from 'child_process';
import os from 'os';
import fs from 'fs';

// 网络接口定义
interface NetworkInterfaceInfo {
  address: string;
  netmask: string;
  family: string;
  mac: string;
  internal: boolean;
  cidr: string | null;
}

/**
 * 服务器管理器类，负责创建和管理HTTP服务器
 */
export class ServerManager {
  private app: express.Express;
  private server: http.Server | https.Server | null = null;
  private config: ServerConfig;
  private logger: Logger;

  constructor(config: ServerConfig) {
    this.config = config;
    this.logger = Logger.getInstance();
    this.app = express();
  }

  /**
   * 启动服务器
   */
  public start(): void {
    // 检查目录是否存在
    if (!FileUtils.exists(this.config.directory)) {
      this.logger.error(`目录不存在: ${this.config.directory}`);
      process.exit(1);
    }

    if (!FileUtils.isDirectory(this.config.directory)) {
      this.logger.error(`路径不是目录: ${this.config.directory}`);
      process.exit(1);
    }

    // 配置中间件
    const middlewareFactory = new MiddlewareFactory(this.config);
    middlewareFactory.configureMiddleware(this.app);

    // 决定创建HTTP服务器还是HTTPS服务器
    if (this.config.security?.https?.enabled) {
      try {
        const certPath = this.config.security.https.cert;
        const keyPath = this.config.security.https.key;

        if (!certPath || !keyPath) {
          this.logger.error('HTTPS已启用，但证书或密钥文件路径未指定');
          process.exit(1);
        }

        // 检查证书和密钥文件是否存在
        if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
          this.logger.error(`HTTPS证书或密钥文件不存在: ${!fs.existsSync(certPath) ? certPath : keyPath}`);
          process.exit(1);
        }

        const httpsOptions = {
          cert: fs.readFileSync(certPath),
          key: fs.readFileSync(keyPath)
        };

        // 创建HTTPS服务器
        this.server = https.createServer(httpsOptions, this.app);
        this.logger.info('已启用HTTPS服务');
      } catch (error) {
        this.logger.error(`配置HTTPS失败: ${error instanceof Error ? error.message : String(error)}`);
        process.exit(1);
      }
    } else {
      // 创建HTTP服务器
      this.server = http.createServer(this.app);
    }

    this.server.listen(this.config.port, () => {
      const address = this.server?.address() as AddressInfo;
      const port = address.port;
      const host = address.address === '::' ? 'localhost' : address.address;
      const protocol = this.config.security?.https?.enabled ? 'https' : 'http';
      const url = `${protocol}://${host}:${port}`;

      this.logger.info(`服务器启动成功，提供目录: ${path.resolve(this.config.directory)}`);
      this.logger.info(`服务器地址: ${url}`);

      // 显示本地网络接口
      this.displayNetworkInterfaces();

      // 如果配置了自动打开浏览器
      if (this.config.openBrowser) {
        this.openBrowser(url);
      }
    });

    this.server.on('error', (err: Error) => {
      if ((err as any).code === 'EADDRINUSE') {
        this.logger.error(`端口 ${this.config.port} 已被占用，请尝试其他端口`);
      } else {
        this.logger.error(`服务器错误: ${err.message}`);
      }
      process.exit(1);
    });
  }

  /**
   * 停止服务器
   */
  public stop(): void {
    if (this.server) {
      this.server.close(() => {
        this.logger.info('服务器已关闭');
      });
    }
  }

  /**
   * 显示网络接口信息
   */
  private displayNetworkInterfaces(): void {
    const interfaces = os.networkInterfaces();
    const addresses: string[] = [];
    const protocol = this.config.security?.https?.enabled ? 'https' : 'http';

    Object.keys(interfaces).forEach(name => {
      interfaces[name]?.forEach((iface: NetworkInterfaceInfo) => {
        // 只显示IPv4地址，跳过内部地址
        if (iface.family === 'IPv4' && !iface.internal) {
          addresses.push(`${protocol}://${iface.address}:${this.config.port}`);
        }
      });
    });

    if (addresses.length > 0) {
      this.logger.info('在网络上可通过以下地址访问:');
      addresses.forEach(addr => {
        this.logger.info(`  ${addr}`);
      });
    }
  }

  /**
   * 打开浏览器
   */
  private openBrowser(url: string): void {
    const command = process.platform === 'win32' ? 'start' :
      process.platform === 'darwin' ? 'open' : 'xdg-open';

    exec(`${command} ${url}`, (error) => {
      if (error) {
        this.logger.error(`无法打开浏览器: ${error.message}`);
      }
    });

    this.logger.info(`已尝试在浏览器中打开: ${url}`);
  }
}
